﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DevExpress.ExpressApp.Editors;
using DevExpress.ExpressApp.Utils;
using DevExpress.ExpressApp.Model;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using System.Windows.Forms;
using DevExpress.XtraEditors.Repository;
using DevExpress.ExpressApp.Win.Editors;

namespace WinSCM.Module.PropertyEditors
{
    [PropertyEditor(typeof(System.Enum), false)]
    public class EnumPropertyEditorEx : EnumPropertyEditor
    {
        private EnumDescriptor enumDescriptor;
        private object noneValue;
        public EnumPropertyEditorEx(Type objectType, IModelMemberViewItem model)
            : base(objectType, model)
        {
        }
        private bool TypeHasFlagsAttribute()
        {
            return GetUnderlyingType().GetCustomAttributes(typeof(FlagsAttribute), true).Length > 0;
        }
        protected override object CreateControlCore()
        {
            CheckedComboBoxEdit checkedEdit = new CheckedComboBoxEdit();
            if (TypeHasFlagsAttribute())
                return checkedEdit;
            return base.CreateControlCore();
        }
        protected override RepositoryItem CreateRepositoryItem()
        {
            if (TypeHasFlagsAttribute())
                return new RepositoryItemCheckedComboBoxEdit();
            return base.CreateRepositoryItem();
        }
        protected override void SetupRepositoryItem(RepositoryItem item)
        {
            base.SetupRepositoryItem(item);
            if (TypeHasFlagsAttribute())
            {
                enumDescriptor = new EnumDescriptor(GetUnderlyingType());
                RepositoryItemCheckedComboBoxEdit checkedItem = ((RepositoryItemCheckedComboBoxEdit)item);
                checkedItem.BeginUpdate();
                checkedItem.Items.Clear();
                noneValue = GetNoneValue();
                //checkedItem.SelectAllItemVisible = false;
                //Dennis: this is required to show localized items in the editor.
                foreach (object value in enumDescriptor.Values)
                    if (!IsNoneValue(value))
                        checkedItem.Items.Add(value, enumDescriptor.GetCaption(value), CheckState.Unchecked, true);
                //Dennis: use this method if you don't to show localized items in the editor.
                //checkedItem.SetFlags(GetUnderlyingType());
                checkedItem.EndUpdate();
                checkedItem.ParseEditValue += checkedEdit_ParseEditValue;
                checkedItem.CustomDisplayText += checkedItem_CustomDisplayText;
            }
        }
        private void checkedEdit_ParseEditValue(object sender, ConvertEditValueEventArgs e)
        {
            if (string.IsNullOrEmpty(Convert.ToString(e.Value)))
            {
                ((CheckedComboBoxEdit)sender).EditValue = noneValue;
                e.Handled = true;
            }
        }
        private void checkedItem_CustomDisplayText(object sender, CustomDisplayTextEventArgs e)
        {
            if (!IsNoneValue(e.Value) || enumDescriptor == null) return;
            e.DisplayText = enumDescriptor.GetCaption(e.Value);
        }
        private bool IsNoneValue(object value)
        {
            if (value is string) return false;
            int result = int.MinValue;
            try
            {
                result = Convert.ToInt32(value);
            }
            catch { }
            return 0.Equals(result);
        }
        private object GetNoneValue()
        {
            return Enum.ToObject(GetUnderlyingType(), 0);
        }
    }
}